Curso de ScriptVox Intermedirio - Aula 9 - Prof. Oswaldo Vernet - iNCE/UFRJ

Vamos retomar, nesta aula, a implementao do jogo de cartas, iniciada na Aula 8.
Transcrevemos, a seguir, o programa principal, acrescido de algumas linhas que 
informam o resultado final do jogo:

* incio do programa principal
vez := 1
pontos_computador := 0
pontos_usurio := 0
embaralha_monte ()
enquanto monte_tem_cartas ()
	carta := compra_carta ()
	pontos := pontua_carta ()
	se vez = 0 
		pontos_computador := pontos_computador + pontos
		escreve "Seu adversrio comprou a carta " carta " e acumulou " pontos_computador " pontos at agora"
	seno
		pontos_usurio := pontos_usurio + pontos
		escreve "Voc comprou a carta " carta " e acumulou " pontos_usurio " pontos at agora"
	fim se
	vez := 1 - vez
fim enquanto

se pontos_usurio > pontos_computador
	escreve "Parabns, o placar foi " pontos_usurio " x " pontos_computador ", voc venceu. Batata frita."
seno
se pontos_usurio = pontos_computador
	escreve "O placar foi " pontos_usurio " x " pontos_computador ", houve empate."
seno
	escreve "Lamento, o placar foi " pontos_usurio " x " pontos_computador ", voc perdeu. Hahahaha."
fim se
* fim do programa principal

Se voc cumpriu direitinho sua tarefa, providenciou a funo embaralha_monte,
que, conforme combinado, deve produzir uma lista de cartas embaralhadas e guard-la na
varivel global "monte".

Pois bem.  sobre esta lista guardada na varivel "monte" que as duas operaes seguintes
(monte_tem_cartas e compra_carta) vo agir. Verificar se o monte ainda tem cartas corresponde 
a verificar se a lista  diferente da lista vazia. Portanto, a funo monte_tem_cartas dever 
apenas retornar o resultado deste teste. Assim:

funo monte_tem_cartas ()
    retorna monte <> []
fim funo

O operador menor maior "<>" faz exatamente o contrrio do operador de igualdade. Ele produz
o resultado VERDADEIRO se os operandos so diferentes e o resultado FALSO se os operandos
no so diferentes, ou seja, se eles so iguais. Portanto, se a varivel "monte" armazenar 
uma lista vazia, a funo retornar zero (que significa FALSO); caso contrrio, a funo
retornar um (que significa VERDADEIRO). O valor de retorno da funo  usado no comando
ENQUANTO.

Voc dever estar se perguntando por que fazer uma funo que se resume a uma s linha de
cdigo.  No seria mais prtico escrever diretamente este teste no comando ENQUANTO, em vez
de ter que chamar uma funo e usar o valor que ela retorna?  Se este questionamento ainda
persiste, releia a aula anterior; l explicamos por que construir uma funo para cada
operao.

Comprar uma carta  uma operao igualmente fcil de implementar: todas as cartas disponveis
so elementos de uma lista que est armazenada na varivel "monte". Comprar uma delas significa
retirar uma carta desta lista, diminuindo em uma unidade a sua cardinalidade. A questo :
qual carta retirar?

Em princpio, qualquer uma, no faz diferena. Mas vamos pensar um pouco em como se retira
uma carta da lista. A funo do ScriptVox que faz isso chama-se RETIRA e espera dois parmetros:
o primeiro  a lista que estamos tratando; o segundo  uma posio vlida na lista. O que
significa uma posio vlida?  Significa um nmero inteiro que deve estar entre zero
(a primeira posio da lista) e o tamanho da lista menos um (que  a ltima posio da
lista). Qualuer outro inteiro  invlido, pois no corresponde a uma posio em que haja
elemento da lista.

Poderamos pensar em sortear um nmero inteiro entre zero e o tamanho da lista menos um.
A funo RAND faria isto para ns. Entretanto, se pensarmos um pouquinho mais, verificaremos
o seguinte: a lista certamente est povoada no momento em que um dos jogadores vai comprar
uma carta. Por que podemos garantir isso?  Porque, quando a lista fica vazia, o teste do
comando ENQUANTO vai falhar e o bloco no ser executado. Portanto, temos certeza de que
a lista tem, pelo menos, um elemento. Isto significa que ela tem pelo menos a posio 
zero ocupada. Podemos, ento, retirar sempre o elemento da posio zero, j que sabemos, 
com certeza, que ele existe. Alm disso, este elemento  desconhecido, pois o monte de
cartas est embaralhado.

Nossa funo compra_carta ficar assim:

funo compra_carta ()
    retorna retira (monte, 0)
fim funo

Novamente uma funo de uma nica linha. E o que essa linha faz?  Ela simplesmente produz
como valor de retorno da funo o valor da expresso que se segue ao comando RETORNA.
E que expresso  essa? Ela consiste em chamar a funo RETIRA, passando como parmetros
a lista (que est na varivel global "monte") e a posio (no caso, zero). Ento esta
nica linha funcionar assim: ela vai fazer com que o valor de retorno da funo compra_carta
seja exatamente o que a chamada da funo RETIRA retornar. E o que a funo RETIRA retorna?
Ela retorna o elemento que estava na lista na posio indicada pelo segundo parmetro.
Por que dissemos estava? Porque no est mais: ele foi retirado da lista. Portanto, usar
o valor de retorno da funo RETIRA  importante quando desejamos saber quem saiu da lista.

S para recordar, os elementos da lista so os nomes das cartas e, portanto, so cadeias de
caracteres. Logo, a funo compra_cartas retornar sempre uma cadeia com o nome da
carta que foi comprada. E qual varivel global recebe o valor retornado pela funo
compra_carta?  A varivel "carta". 

A ltima operao, chamada pontua_carta. Sua misso  descobrir o valor da carta cujo
nome est guardado na varivel global "carta". Lembra-se de como construmos os nomes das
cartas na aula passada? Era exatamente o valor da carta, expresso em caracteres numricos,
seguido da preposio "de", seguida do nome do naipe. Portanto, nossa resposta est na
primeira parte do nome da carta. Lembra-se da funo PALAVRA? Ela espera dois parmetros:
um nmero inteiro e uma cadeia; ela busca na cadeia e retorna a palavra cuja ordem  dada pelo
primeiro parmetro. Assim, se passarmos o inteiro um como parmetro, ela buscar a primeira
palavra; se passarmos dois, ela buscar a segunda; e assim por diante. Em qual palavra
est o valor da carta que queremos?  Exatamente na primeira.

Logo, a nossa funo pontua_carta ser tambm uma funo de uma linha apenas:

funo pontua_carta ()
    retorna palavra (1, carta)
fim funo

Se voc cumpriu a tarefa da aula passada, que era completar a funo embaralha_monte,
que tal, agora, voc colocar este script em execuo no interpretador?

H um ltimo ponto que precisamos melhorar neste script.  pouco educado chamar uma 
Dama de doze. Mas, com a opo feita na aula passada para representao dos nomes das cartas, 
isto est acontecendo. No exerccio prtico, voc encontrar o conserto provisrio para isto. 
O conserto definitivo ser tema da prxima aula.  


EXERCCIOS

Perguntas de Estudo Dirigido

1.  Na funo compra_carta, optamos por retirar sempre o elemento da posio zero da lista.
    Isto significa que o ScriptVox dever mover todos os elementos seguintes de uma posio para
	trs, para que no fique um buraco com elemento faltando na primeira posio da lista.
	Ns no percebemos este esforo, mas o ScriptVox certamente fica cansado tendo que empurrar
	todos os elementos para trs cada vez que se compra uma carta. J que  indiferente remover 
	o elemento da posio zero ou qualquer outro, pois as cartas esto embaralhadas, qual elemento
	voc removeria a fim de no cansar o ScriptVox?

2.  Funes como compra_carta e pontua_carta possuem uma caracterstica especial: elas simplesmente
    chamam uma outra funo e retornam o que esta outra funo retorna (uma espcie de terceirizao
	de servios). No caso de compra_carta, ela vai retornar o que a funo RETIRA retornar; no caso de 
	pontua_carta, ela vai retornar o que a funo PALAVRA retornar. Faa uma analogia entre 
	este comportamento e algum fato da vida diria.
	
3.  Voc deve ter percebido que este jogo no tem graa nenhuma. O usurio fica teclando nter a
    vida toda e o computador vai dizendo quantos pontos cada um tem. Ningum jogar este jogo mais
	de uma vez na vida. O que falta  alguma interatividade em que o usurio participe do jogo,
    no ficando totalmente passivo. Analise em que ponto do jogo alguma interatividade poderia ser
    introduzida.

4.  A vantagem de encapsular as operaes essenciais do jogo em funes  a independncia que se
    consegue entre o funcionamento do jogo e a maneira como os dados esto representados. Na prxima
    aula, por exemplo, iremos mudar a maneira de representar as cartas e veremos que o programa
    principal vai continuar o mesmo. Ou seja, o programa principal captura exatamente o que h
	de essencial no jogo e as funes que implementam as operaes  que lidam com detalhes de
	representao. Pense sobre isso.	

5.  Por que o script, quando parabeniza o usurio pela vitria, escreve Batata Frita?


Exerccio de avaliao (enviar para scriptvox@gmail.com at o meio-dia de 16 de fevereiro de 2012)

A tarefa agora  corrigir os nomes das cartas. Para isto, acrescentamos uma lista, que  inicializada
no incio do script. As posies nesta lista correspondem a valores de cartas e os elementos destas
posies, aos nomes. Assim:

nomes := [ "", "s", "Dois", "Trs", "Quatro", "Cinco", "Seis", "Sete", "Oito", "Nove", "Dez", "Valete", "Dama", "Rei" ]

A ideia  a seguinte: o valor da carta ns sabemos. Ele foi extrado da primeira palavra do nome da carta.
Para obter o nome correto, basta indexar a lista "nomes" usando o valor da carta. Repare que o elemento 
da posio zero (ou seja, o primeiro da lista) pode ser qualquer coisa, pois nunca ser usado, 
j que nenhuma carta tem valor zero. 

Escreva a funo nome_da_carta, que recebe como parmetro uma cadeia com o nome antigo da carta 
e retorna outra cadeia, contendo o nome correto da carta. Assim, se o parmetro contiver a cadeia

"11 de copas"

a funo dever retornar

"Valete de copas"

Use a sua funo nos dois comandos ESCREVE do script, para escrever o nome correto da carta.

Bom estudo!

Oswaldo Vernet







